

$(function () { 
  
    var $form = $('.right>form'); 
    var pp = new Project($form); 
    //var nowItem = -1;
    $(document) 
        //删除项
        .on('dblclick', '#Lists li', function () {
            var key = $(this).attr('data-key');
            async_confirm("你确认要删除该项？",function(){ 
                pp.getProject(function(pj,save){ 
                    if(pj.list[key]){
                        delete pj.list[key]; 
                        save(); 
                    } 
                });
            });
            return false;
        })   
        //右侧折叠按钮 
        .on('click','.ttt',function(){
            if($('body>.panel').attr('style')){
                $('body>.panel').attr('style','')
            }else{
                $('body>.right').attr('style','width:auto;margin-left:10px;');
                $('body>.left').attr('style','display:none'); 
            }
            return false;
        })
        //选择项
        .on('click', '#Lists li', function () {
            var key = $(this).attr('data-key');
            pp.loadItem(  key );
        })

        //新建项目组
        .on('click', '.NewProject', function () { 
            async_prompt("项目组名", "新项目组",function(name){ 
                pp.newProject(name); 
            });
        })
        //删除项目组
        .on('click', '.DelProject', function () {
            pp.delProject(); 
        })
        //清空项目组
        .on('click', '.ClrProject', function () {
            pp.getProject(function(pj,next){
                pj.list = {};
                next();
            }); 
        })
        //重命名项目组
        .on('click', '.RenProject', function () {
            console.log('0');
            pp.getProject(function(pj,next){ 
                async_prompt("新名字", pj.name,function(name){
                    pj.name = name;    
                    next();
                }); 
            });
        })

        //切换项目组
        .on('change', '.ProjectList', function () {
            pp.loadProject( $(this).val() ); 
        })
        //导出
        .on('click', '.ExportDoc', function () { 
            pp.exportDoc('api');
        })
        .on('click', '.ImportJson', function () {
            pp.importJson('api');
        })
        .on('click', '.ExportJson', function () {
            pp.exportJson('api');
        })
        .on('mouseout','input[type=checkbox]',function(e){
            if(e.buttons==1) 
                $(this).prop('checked',!$(this).prop('checked')); 
        })

 
        //标题
        .on('click', '.New', function () {
            pp.loadItem();
            return false;
        })
        .on('click', '.Save', function () {
            $(this).parents('form').unbind().one('submit', function (e) {
                pp.saveItem($form.attr('data-index'));  
                return false;
            });
        })
        .on('click', '.Clone', function () {
            $(this).parents('form').unbind().one('submit', function (e) {
                pp.saveItem(Date.now()); //拷贝设置新ID
                return false;
            });
        }) 
        .on('click', '.Send', function () {
            $(this).parents('form').unbind().one('submit', function (e) {
                pp.sendItem();
                return false;
            });
        }) 

        .on('click','.Head',function () {
            var $this = $(this);
            async_prompt("请求前缀",$this.html( ) ,function(t){  
                cache('head',function(){return t;});
                $this.html(t);
            }); 
            return false;
        })
        // }); 
        //$(function(){
        //     $(document)

        //内容
        .on('change', 'select[name=type]', function () {
            var $v = $(this).parents('tr').find('[name=val]');
            $v.attr('type', this.value);
            return false;
        })
        .on('click', '.TabRemove', function () {
            $(this).parents('tr').remove();
            initdragsort(pp);
            return false;
        })
        .on('click', '.NewParams', function () {
            var $ls = $('.Params');
            var $tr = newParams($ls)
            initdragsort(pp);
            return false;
        })
        .on('click', '.NewHeaders', function () {
            var $ls = $('.Headers');
            var $tr = newHeaders($ls);
            initdragsort(pp);
            return false;
        })
        .on('click', '.NewResponse', function () {
            var $ls = $('.Response');
            var $tr = newResponse($ls);
            initdragsort(pp);
            return false;
        }) 
        //添加新行
        .on('focus','.glyphicon-plus',function(e){
            var $this = $(this).click();    
            setTimeout(function(){
                $this.parents('.brick ').find('tr:last input:first').focus();
            });
            return false; 
        })
        //添加发送
        .on('keydown','.right input',function(e){ 
            $('body').addClass('unsave'); 
            //enter
            if(e.keyCode=='13'){
                $('.Send').click(); 
                return false;
            } 
            // ctrl + s
            if( e.ctrlKey  == true && e.keyCode == 83 ){
                $('.Save').click(); 
                return false;
            }
        })
      
    ;
     
    cache('rigthpanel',function(v){
        var ii = (v.h || v.p || v.r)?v: { h:1, p:2, r:3 };
        for(var k in ii) 
            $('.gridly [data-key='+k+']').attr('data-sort',ii[k]);   
        $('.gridly').sortBy('data-sort');
        if(!v)return ii;
    }) 
    cache('head',function(v){ 
        $('.Head').html(v.substr?v:"http://");
    });
    initdragsort(pp); 
});
function initdragsort(pp){  
 
    var $elem = $('.table tbody ');
    $elem.dragsort('destroy')
    $elem.dragsort({ 
        dragSelectorExclude:"input,textarea,pre,select,textarea",
        dragSelector: ".TabMove",  
        dragEnd: function(e) {   }, 
    });  
 
    var $elem = $("#Lists")
    $elem.dragsort('destroy')
    $elem.dragsort({   
        dragSelectorExclude:"input,textarea,pre,select,textarea",
        dragSelector: "span",  
        dragEnd: function(e) {      
            pp.getProject(function(pj,next){ 
                $('#Lists>*').each(function(){
                    pj.list[$(this).attr('data-key')].sort=$(this).index()+1;
                })
                next();   
            }); 
        }, 
    }); 
    
    var $elem = $(".gridly")
    $elem.dragsort('destroy');  
    $elem.dragsort({ 
        dragSelectorExclude:"input,textarea,pre,select,textarea",
        dragSelector: ".panel-heading,.nav",  
        dragEnd: function(e) {  
            cache('rigthpanel',function(ii){ 
                $('.gridly>*').each(function(){
                    ii[$(this).attr('data-key')]=$(this).index()+1;
                })
                return ii;
            }); 
        }, 
    });

    
}

$.fn.sortBy=function(key){ 
    var elems = $(this).find('>*').sort(function(a,b){  
        return parseInt($(a).attr(key)) > parseInt($(b).attr(key))  ? 1 : -1;
    });
    return $(this).empty().append(elems); 
}
 
function Project($form){
    var project ={};// {'0':{name:'新项目组',list:{}}} ;
    var now = ''; 
    var _this = this;
    _this.loadProject = function( _def_proj ) {  
        var $list = $('.ProjectList').empty();    
        for (var key in project) {
            var item = project[key]; 
            if (!_def_proj) _def_proj = key;
            $("<option value=" + key + ">" + item.name + "</option>").appendTo($list);
        } 
        if(!_def_proj){
            project[ _def_proj = Date.now() ] = {name:'新项目组:'+Date.now(),list:{} } ; 
            for (var key in project) {
                var item = project[key];  
                $("<option value=" + key + ">" + item.name + "</option>").appendTo($list);
            } 
            saveProject();
        } 
        now = _def_proj ;
        _this.loadList(); 
    }
    _this.getProject = function (cb){  
        cb( project[now] , function(){  
            _this.loadProject( now );  
            saveProject();  
        });   
    }
    _this.newProject = function(name){ 
        var key = Date.now();
        project[key] = { name: name, list: {}, };   
        _this.loadProject(key);   
        saveProject(); 
    }
    _this.delProject = function(){  
        delete project[now]; 
        now = '';
        _this.loadProject(); 
        saveProject();
    }  
    _this.loadList=function( _def_item ){ 
        var $list = $('#Lists').empty();  
        if(!project[now])return;
        var list = project[now].list;
        for (var key in list) {
            var item = list[key];
            var $li = $("<li data-sort="+item.sort+" data-key=" + key + " class='pos'><a>" + item.name + "<span class='pos-right'>" + item.method + "</span></a></li>").appendTo($list);
        }
        $list.sortBy('data-sort');
        $('.ProjectList').val(now);//??????
        if(_def_item)_this.loadItem( _def_item );
    
    } 
    _this.loadItem = function(i) {
        $('body').removeClass('unsave');//
        
        i = i || Date.now();  
        $('#Lists li').removeClass('active');
        $('#Lists li[data-key="'+i+'"]').addClass('active');  
        var item =  project[now]['list'][i] || {  params: [], headers: [], response: [], };

        $form.attr('data-index', i); 

        $form.find('[name=Name]').val(item.name);
        $form.find('[name=Url]').val(item.url);
        $form.find('[name=Method]').val(item.method || 'GET');
        $form.find('[name=Example]').val(item.example ); 
        
        exview(item.example); 

 
 
        var $table = $form.find('.Params').empty();
        item.params.forEach(function (elem) {
            newParams($table, elem);
        }, this); 

        var $table = $form.find('.Headers').empty();
        item.headers.forEach(function (elem) {
            newHeaders($table, elem);
        }, this); 
        var $table = $form.find('.Response').empty();
        item.response.forEach(function (elem) {
            newResponse($table, elem);
        }, this);


        initdragsort(_this); 
    }
    _this.saveItem = function(i) { 
        $('body').removeClass('unsave'); 

        var item =  getItem();  
        if(!project[now]['list'][i]) {
            i = Date.now();//不存在就新建新ID  
            item.sort = $('#Lists li').length+1; 
        } 
        project[now]['list'][i] =item; 
        _this.loadList(i); 
        saveProject();
    }
    _this.sendItem = function () { 
        var item = getItem();
        var ajax = $.ajax({
            url: $('.Head').html()+ item.url,
            type:item.method,
            data: new function(){
                var d = {};
                item.params.forEach(function(elem){
                    if(elem.iss)d[elem.key]=elem.val;
                });
                return d;
            },  
            headers: new function(){
                var d = {};
                item.headers.forEach(function(elem){
                    d[elem.key]=elem.val;
                });
                return d;
            }, 
            error:function(obj,b,c){
                console.log([obj,b,c]); 
                exview(obj.responseText);  
                $('.Status').html('\
                    <span class="badge"> CODE: '+obj.status+' </span>\
                    <span class="badge"> STATUS: '+obj.statusText+' </span>\
                '); 
            },
            success: function (data, text, obj) {
                console.log(data);
                $('.Status').html('\
                    <span class="badge"> CODE: '+obj.status+' </span>\
                    <span class="badge"> STATUS: '+obj.statusText+' </span>\
                '); 
                $('#EXResponse pre').text(ajax.getAllResponseHeaders());   
                exview(obj.responseText); 
            },
        });

    }
    _this.exportDoc = function(file) {   
        explodList(project,function(project,next){ 
            var str = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40">\
            <meta http-equiv="content-type" content="application/vnd.ms-word; charset=UTF-8">\
            <head> <meta charset="utf-8" /><style>td{padding:8px}div{line-height:36px}table,td{border:1px solid #ccc;border-collapse:collapse}</style></head>\
            <body >\n'; 
            for(var k in project){
                var list = []; 
                for(var i in project[k]['list'])  //排序
                    list[project[k]['list'][i].sort] = project[k]['list'][i]; 
                var name = project[k]['name'];

                str+='<h2>'+name+'</h2>';

                for (var key in list) {
                    var item = list[key]; 
                    str+='<h3>'+item.method+ '  '+item.name+'</h3>';
                    str+="<div><a href='"+item.url+"'>"+item.url+"</a></div>";
                    //str+="<div>请求参数：</div>";
                    str+= "<table width='100%' >"
                    str+=" <tr><td colspan='4'>请求参数：</td></tr>"
                    str+=" <tr><td width='100'>参数<td width='100'>类型<td width='60'>必填<td >备注</tr>";
                    item.params.forEach(function(elem) {
                        str+="<tr>";
                        str+="<td >"+elem.key+"</td>";
                        str+="<td >"+elem.type+"</td>";
                        str+="<td >"+(elem.iss?'是':'否')+"</td>"; 
                        str+="<td >"+elem.mark+"</td>";
                        str+="</tr>";
                    }, this);
                    str+="</table>";
                    str+="<br>"; 
                    //str+="<div>通知结果：</div>";
                    str+= "<table  width='100%'>";
                    str+=" <tr><td colspan='2'>通知结果：</td></tr>";
                    str+=" <tr><td width='100'>参数<td >备注</tr>";
                    item.response.forEach(function(elem) {
                        str+="<tr>";
                        str+="<td>"+elem.key+'</td>'; 
                        str+="<td>"+elem.mark+'</td>'; 
                        str+="</tr>";
                    }, this);
                    str+="</table>";
                    str+="<br>"; 
                    str+= "<table  width='100%'>";
                    str+=" <tr><td >测试例子：</td></tr>";
                    str+=" <tr><td ><pre>" + item.example +"</pre></td></tr>"; 
                    //((item.example && item.example[0]=='{')?JSON.stringify( JSON.parse(item.example) ,undefined,2):item.example) 
                    str+="</table>"; 
                    str+="<br>";
                    str+="<br>";
                    str+="<br>";
                    str+="<br>";
                    str+="<br>"; 
                }  
            } 
            str += "</body></html>";
            
            var cfg = {type: 'saveFile',accepts:[{extensions:['doc']}]};
            chrome.fileSystem.chooseEntry(cfg, function(writableFileEntry) {
                writableFileEntry.createWriter(function(writer) {  
                    $('body').hide();
                    writer.write(new Blob([str], {type: 'application/vnd.ms-word'}));
                    writer.onwriteend = function(e) {
                        $('body').show();
                        next();
                    };
                });
            });
            //downloadFile(file+'.doc','data:application/vnd.ms-word;base64,',str);  
        });   
    } 
    _this.exportJson=function(file){   
        explodList(project,function(project,next){  
            var str = JSON.stringify(project);
            var cfg = {type: 'saveFile',accepts:[{extensions:['json']}]};
            chrome.fileSystem.chooseEntry(cfg,  function(writableFileEntry) {
                writableFileEntry.createWriter(function(writer) {  
                    $('body').hide();
                    writer.write(new Blob([str], {type: 'application/json'}));
                    writer.onwriteend = function(e) {
                        $('body').show();
                        next();
                    };
                });
            });
            //downloadFile(file+'.json','data:application/json;base64,',str);  
        });
    }
    _this.importJson=function(){ 
        var cfg = {type: 'openFile',accepts:[{extensions:['json']}]};
        chrome.fileSystem.chooseEntry(cfg, function(readOnlyEntry) { 
            readOnlyEntry.file(function(file) {
                var fr = new FileReader();  
                fr.onloadend = function(e,r) {  
                    try{ 
                        project = JSON.parse(this.result||"{}");  
                        _this.loadProject();  
                        saveProject();
                    }catch(e){
                        async_confirm(e.message);
                    } 
                };
                fr.readAsText(file);
            });
        }); 
        // $('<input type="file">').appendTo('body').change(function(){
        //     var fr = new FileReader();  
        //     fr.onloadend = function(e,r) {  
        //         try{ 
        //             project = JSON.parse(this.result);  
        //             _this.loadProject();  
        //             saveProject();
        //         }catch(e){
        //             async_confirm(e.message);
        //         }
        //     };
        //     fr.readAsText(this.files[0]); 
        // }).click();
    }
    function exview(str){ 
        str = str || '';
        if(str[0]=='{'){ 
            str = JSON.stringify(JSON.parse(str), undefined, 2) ;//格式化
            //str = str.replace(/([\{\[])[\n\r]+([^\,\{]{0,30})[\r\n]/im,'$1$2' )
            $('[name=Example]').val( str );
            $('#EXPreview pre').html( syntaxHighlight(str) ); 
        } else {
            $('[name=Example]').val(str);

            $('#EXPreview pre').text(str);
            $('#EXPreview pre').html(syntaxHighlight2($('#EXPreview pre').html() ) );
        } 
        if(str){ 
            $('[href="#EXPreview"]').tab('show'); 
        }else{
            $('[href="#EXRequest"]').tab('show'); 

        }
    }

    function getItem( ) {
        return { 
            sort: $('#Lists li[data-key="'+$form.attr('data-index')+'"]').attr('data-sort') || ($('#Lists li.active').attr('data-sort'))|| '1',
            name: $form.find('[name=Name]').val(),
            url: $form.find('[name=Url]').val(),
            method: $form.find('[name=Method]').val(),
            example: $form.find('[name=Example]').val(),
            params: new function () {
                var data = [];
                $form.find('.Params tr').each(function () {
                    var $this = $(this);
                    data.push({
                        'key': $this.find('[name=key]').val(),
                        'val': $this.find('[name=val]').val(),
                        'type': $this.find('[name=type]').val(),
                        'mark': $this.find('[name=mark]').val(),
                        'iss': !!$this.find('[name=iss]:checked').length,
                    })
                });
                return data;
            },
            headers: new function () {
                var data = [];
                $form.find('.Headers tr').each(function () {
                    var $this = $(this);
                    data.push({
                        'key': $this.find('[name=key]').val(),
                        'val': $this.find('[name=val]').val(),
                        'iss': !!$this.find('[name=iss]:checked').length,
                    })
                });
                return data;
            },
            response: new function () {
                var data = [];
                $form.find('.Response tr').each(function () {
                    var $this = $(this);
                    data.push({
                        'key': $this.find('[name=key]').val(), 
                        'mark': $this.find('[name=mark]').val(),
                        'iss': !!$this.find('[name=iss]:checked').length,
                    })
                });
                return data;
            },
        };
    } 
    function saveProject(){
        console.log('save'); 
        cache('project',function(val){ 
            return project; 
        }); 
    } 
    function syntaxHighlight(json) {
        if (typeof json != 'string') {
            json = JSON.stringify(json, undefined, 2); 
        }
        json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
        return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function(match) {
            var cls = 'number';
            if (/^"/.test(match)) {
                if (/:$/.test(match)) {
                    cls = 'key';
                } else {
                    cls = 'string';
                }
            } else if (/true|false/.test(match)) {
                cls = 'boolean';
            } else if (/null/.test(match)) {
                cls = 'null';
            } 
            return '<span class="' + cls + '">' + match + '</span>';
        });
    }
    function syntaxHighlight2(html) {
        if(!html)return ;
        html = html.replace(/(&lt;\/?)(html|head|meta|title|script|link|body|div|span|h1|h2|h3|h4|ul|li|ol|dl|dd|dt|img|a|b|s|p|pre|code)/g,function($0,$1,$2){ 
            return $1+'<span class="html">' + $2 + '</span>';
        });
        html = html.replace(/(&lt;\/?)(form|input|select|button|option)/g,function($0,$1,$2){
            return $1+'<span class="option">' + $2 + '</span>';
        });
        html = html.replace(/(&lt;!--[\s\S]*?)--&gt;/g,function($0,$1,$2){
            return '<span class="string">' + $0 + '</span>';
        });
        return html;
    }
    cache('project',function(val){ 
        console.log('load');
        project = val;
        _this.loadProject(); 
    });
}
 
function cache(name,func){
    var isapp = chrome && chrome.storage && chrome.storage.local;
    cache[name]?success():init(); 
    function init(){
        if(isapp){
            chrome.storage.local.get(name,function(val){  
                try{
                    cache[name] = JSON.parse( val[name] || '{}');
                }catch(e){  }    
               success();
            }); 
        }else{ 
            try{
                cache[name] =  JSON.parse(localStorage[name]||'{}'); 
            }catch(e){ }   
            success();
        }   

    }
    function success(){  
        var value = func(cache[name]);  
        if(value){
            cache[name] = value;
            if(isapp){ 
                var v = {};
                v[name]=JSON.stringify(cache[name]);
                chrome.storage.local.set(v);  
            }else{ 
                localStorage[name] = JSON.stringify(cache[name]); 
            }
        }  
    } 
}


function explodList(project,cb){ 
    var $m = $('#modal').modal('show'); 
    var $body=$m.find('.modal-body').show().empty();
    $m.find('.modal-title').html("选择导出项");
    $m.find('form').unbind().submit(function(){  
        var ls = [];
        var title = $m.find('[name=title]').val();
        $body.find('input:checked').each(function(){
            ls.push(project[$(this).attr('name')]);
        });
        cb(ls,function(){ 
            $('#modal').modal('hide');
        });
        return false;
    });
    for(var i in project)  
        $body.append('<div><input name="'+i+'" type="checkbox" checked > '+project[i].name+'</div>'); 
}

function async_prompt(title,msg,cb){ 
    var $m = $('#modal').modal('show');
    var $input = $("<input class='form-control' value='"+msg+"' required >");
    $m.find('.modal-title').html(title);
    $m.find('.modal-body').show().empty().append($input);
    $m.find('form').unbind().submit(function(){ 
        if(cb)cb.call($m[0],$input.val());
        $('#modal').modal('hide');
        return false;
    });
}
function async_confirm(title,cb){
    var $m = $('#modal').modal('show');
    $m.find('.modal-title').html(title);
    $m.find('.modal-body').hide();
    $m.find('form').unbind().submit(function(){
        if(cb)cb.call( );
        $('#modal').modal('hide');
        return false;
    });

} 

function newParams($table, elem) {
    elem = elem || {};
    var option = "<option>Text</option><option>File</option><option>Number</option>";
    var $tr = $('<tr>').html('\
    <td style="width:20%"><input  class="form-control" type="text" name="key" required  placeholder="key" value="'+ (elem.key || '') + '"></td>\
    <td style="width:150px"><input  class="form-control" type="text" name="val" placeholder="value" value="'+ (elem.val || '') + '"></td>\
    <td style="width:94px"><select  tabindex="-1" class="form-control" name="type" >'+ (option) + '</select></td>\
    <td><input  class="form-control" type="text" name="mark" placeholder="mark" value="'+ (elem.mark || '') + '"></td>\
    <td style="width:1">\
        <input class="btn " type="checkbox"  tabindex="-1" name="iss" '+ (elem.iss === false ? "" : "checked") + '> \
        <button class="btn btn-default glyphicon glyphicon-resize-vertical TabMove" type="button" tabindex="-1" ></button> \
        <button class="btn btn-default glyphicon glyphicon-remove TabRemove" type="button"   tabindex="-1" ></button>\
    </td>').appendTo($table);
    if(elem.type){
        $tr.find('[name=type]').val(elem.type);
        $tr.find('[name=val]').attr('type', elem.type);
    }
    return $tr;
}
function newHeaders($table, elem) {
    elem = elem || {};
    var $tr = $('<tr>').html('\
    <td  style="width:120px"><input  class="form-control" type="text" name="key" required placeholder="key" value="'+ (elem.key || '') + '"></td>\
    <td><input  class="form-control" type="text" name="val" placeholder="value" value="'+ (elem.val || '') + '"></td>\
    <td style="width:1">\
        <button class="btn btn-default glyphicon glyphicon-resize-vertical TabMove" type="button"  tabindex="-1" ></button> \
        <button class="btn btn-default glyphicon glyphicon-remove TabRemove" type="button"  tabindex="-1" ></button>\
    </td>').appendTo($table); 
    return $tr;
}
function newResponse($table, elem) {
    elem = elem || {};
    var $tr = $('<tr>').html('\
    <td  style="width:20%"><input  class="form-control" type="text" name="key" required placeholder="key" value="'+ (elem.key || '') + '"></td>\
    <td><input  class="form-control" type="text" name="mark" placeholder="mark" value="'+ (elem.mark || '') + '"></td>\
    <td style="width:1">\
        <input class="btn " type="checkbox"  tabindex="-1" name="iss" '+ (elem.iss === false ? "" : "checked") + '> \
        <button class="btn btn-default glyphicon glyphicon-resize-vertical TabMove" type="button"   tabindex="-1" ></button> \
        <button class="btn btn-default glyphicon glyphicon-remove TabRemove" type="button"  tabindex="-1" ></button>\
    </td>').appendTo($table);
    return $tr;
}


function downloadFile(filename, header, data) {

    var DownloadEvt = null;
    var ua = window.navigator.userAgent;
    if (ua.indexOf("MSIE ") > 0 || !!ua.match(/Trident.*rv\:11\./)) {
        // Internet Explorer (<= 9) workaround by Darryl (https://github.com/dawiong/tableExport.jquery.plugin)
        // based on sampopes answer on http://stackoverflow.com/questions/22317951
        // ! Not working for json and pdf format !
        var frame = document.createElement("iframe");

        if (frame) {
            document.body.appendChild(frame);
            frame.setAttribute("style", "display:none");
            frame.contentDocument.open("txt/html", "replace");
            frame.contentDocument.write(data);
            frame.contentDocument.close();
            frame.focus();

            frame.contentDocument.execCommand("SaveAs", true, filename);
            document.body.removeChild(frame);
        }
    }
    else {
        var DownloadLink = document.createElement('a');

        if (DownloadLink) {
            DownloadLink.style.display = 'none';
            DownloadLink.download = filename;

            if (header.toLowerCase().indexOf("base64,") >= 0)
                DownloadLink.href = header + base64encode(data);
            else
                DownloadLink.href = header + encodeURIComponent(data);

            document.body.appendChild(DownloadLink);

            if (document.createEvent) {
                if (DownloadEvt == null)
                    DownloadEvt = document.createEvent('MouseEvents');

                DownloadEvt.initEvent('click', true, false);
                DownloadLink.dispatchEvent(DownloadEvt);
            }
            else if (document.createEventObject)
                DownloadLink.fireEvent('onclick');
            else if (typeof DownloadLink.onclick == 'function')
                DownloadLink.onclick();

            document.body.removeChild(DownloadLink);
        }
    }
}
function utf8Encode(string) {
    string = string.replace(/\x0d\x0a/g, "\x0a");
    var utftext = "";
    for (var n = 0; n < string.length; n++) {
        var c = string.charCodeAt(n);
        if (c < 128) {
        utftext += String.fromCharCode(c);
        }
        else if ((c > 127) && (c < 2048)) {
        utftext += String.fromCharCode((c >> 6) | 192);
        utftext += String.fromCharCode((c & 63) | 128);
        }
        else {
        utftext += String.fromCharCode((c >> 12) | 224);
        utftext += String.fromCharCode(((c >> 6) & 63) | 128);
        utftext += String.fromCharCode((c & 63) | 128);
        }
    }
    return utftext;
}
function base64encode(input) {
        var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;
        input = utf8Encode(input);
        while (i < input.length) {
          chr1 = input.charCodeAt(i++);
          chr2 = input.charCodeAt(i++);
          chr3 = input.charCodeAt(i++);
          enc1 = chr1 >> 2;
          enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
          enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
          enc4 = chr3 & 63;
          if (isNaN(chr2)) {
            enc3 = enc4 = 64;
          } else if (isNaN(chr3)) {
            enc4 = 64;
          }
          output = output +
                  keyStr.charAt(enc1) + keyStr.charAt(enc2) +
                  keyStr.charAt(enc3) + keyStr.charAt(enc4);
        }
        return output;
      }